#include "csudoku.h"

CSudoku::CSudoku(QObject *parent) : QObject(parent)
{


}

CSudoku::CSudoku(int n)
{
    int i,j;
    srand(time(0));
    do
    {
        for(i=0; i<9; ++i)
        {
            for(j=0; j<9; ++j)
                mp[i][j]=0;
            j=rand()%9;
            mp[i][j]=i+1;
        }
    }
    while(!resolve(ANY));

// 挖窟窿
    for(int k=0; k<n;)
    {
        i=rand()%81;
        j=i%9;
        i=i/9;
        if(mp[i][j]>0)
        {
            mp[i][j]=0;
            ++k;
        }

    }
//printf("(randomized sudoku created with %d blanks.)\n",blanks);
}
CSudoku::CSudoku(int *data)
{
    int *pm=(int*)mp;
    for(int i=0; i<81; ++i)
        pm[i]=data[i];
}
CSudoku::~CSudoku()
{
    return;
}
void CSudoku::display()
{
    for(int i=0; i<9; ++i)
    {
        for(int j=0; j<9; ++j)
        {
            if(mp[i][j]>0)
                printf("< %d >  ",mp[i][j]);
            else
                printf("[   ]  ");
        }
        printf("\n");
    }
}
int CSudoku::resolve(int mod)
{
    smod=mod;
    if(mod==ALL)
    {
        solves=0;
        dfs();
        return solves;
    }
    else if(mod==ANY)
    {
        try
        {
            dfs();
            return 0;
        }
        catch(int)
        {
            return 1;
        }
    }
    return 0;
}
int CSudoku::check(int y,int x,int *mark)
{
    int i,j,is,js,count=0;
    for(i=1; i<=9; ++i)
        mark[i]=0;
    for(i=0; i<9; ++i)
        mark[mp[y][i]]=1;
    for(i=0; i<9; ++i)
        mark[mp[i][x]]=1;
    is=y/3*3;
    js=x/3*3;
    for(i=0; i<3; ++i)
    {
        for(j=0; j<3; ++j)
            mark[mp[is+i][js+j]]=1;
    }
    for(i=1; i<=9; ++i)
        if(mark[i]==0)
            count++;
    return count;
}
void CSudoku::dfs()
{
    int i,j,im=-1,jm,min=10;
    int mark[10];
    for(i=0; i<9; ++i)
    {
        for(j=0; j<9; ++j)
        {
            if(mp[i][j])
                continue;
            int c=check(i,j,mark);
            if(c==0)
                return;
            if(c<min)
            {
                im=i;
                jm=j;
                min=c;
            }
        }
    }
    if(im==-1)
    {
        if(smod==ALL)
        {
            printf("No. %d:\n",++solves);
            display();
            return;
        }
        else if(smod==ANY)
        {
            throw(1);
        }
    }
    check(im,jm,mark);
    for(i=1; i<=9; ++i)
    {
        if(mark[i]==0)
        {
            mp[im][jm]=i;
            dfs();
        }
    }
    mp[im][jm]=0;
}
int CSudoku::getAtom(int x, int y){
    return mp[x][y];
}
bool CSudoku::mydfs(int x,int y){
 //   emit sendThis();
 //   emit try_point(x,y);
    if(x==9) return true;
    bool flag = false;
 //   std::cout << "solve " << x << " " << y << std::endl;
    if(mp[x][y]){
        if(y==8) flag = mydfs(x+1,1);
        else flag = mydfs(x,y+1);
        if(flag) return true;
        else return false;
    }else{
        int k = 3*(x/3) + y/3 ;
        for(int i=0;i<9;i++){
 //           std::cout << "lets try " << i+1 << std::endl;
 //           std::cout << "row " << x << " " << i << " " << row[x][i] << std::endl;
 //           std::cout << "col " << y << " " << i << " " << col[y][i] << std::endl;
 //           std::cout << "grid " << k << " " << i << " " << grid[k][i] << std::endl;
            if(!row[x][i]&&!col[y][i]&&grid[k][i]){
 //               std::cout << "now " << x << " " << y << " " << mp[x][y] << std::endl;
                mp[x][y] = i;
                row[x][i] = true;
                col[y][i] = true;
                grid[k][i] = true;

                if(y==8) flag = mydfs(x+1,1);
                else flag = mydfs(x,y+1);

                if(!flag){
                    mp[x][y] = 0;
                    row[x][i] = false;
                    col[y][i] = false;
                    grid[k][i] = false;
                }else{
                    return true;
                }
            }
        }
    }
    return false;
}

void CSudoku::solve(){

}
